package org.dromara.quickswing;

import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.joran.JoranConfigurator;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.text.CharSequenceUtil;
import com.formdev.flatlaf.util.SystemInfo;
import org.dromara.quickswing.constant.QSConstant;
import org.dromara.quickswing.exception.QSBasedException;
import org.dromara.quickswing.utils.QSArgsUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import raven.toast.Notifications;

import javax.swing.*;
import java.io.File;
import java.io.InputStream;

import static org.dromara.quickswing.constant.QSConstant.DEFAULT_LOG_FILE;

public class QSApplicationInitializer {

    private static final Logger log = LoggerFactory.getLogger(QSApplicationInitializer.class);

    public static void initialize(String[] args, String appName, String dataPath, Runnable afterHandler) {

        String appDataPath = QSArgsUtils.getArgValue(args, QSConstant.KEY_APP_DATA_PATH);
        if (appDataPath == null) {
            appDataPath = FileUtil.getUserHomePath() + File.separator + "." + dataPath.toLowerCase();
        }

        if (!FileUtil.exist(appDataPath)) {
            FileUtil.mkdir(appDataPath);
        }

        System.setProperty(QSConstant.KEY_LOG_FILE, appDataPath + File.separator + DEFAULT_LOG_FILE);

        try (InputStream logbackProdXmlStream = ResourceUtil.getStreamSafe("logback-prod.xml")) {
            LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
            JoranConfigurator configurator = new JoranConfigurator();
            loggerContext.reset();
            configurator.setContext(loggerContext);
            if (logbackProdXmlStream != null) {
                configurator.doConfigure(logbackProdXmlStream);
            } else {
                try (InputStream logbackBaseXmlStream = ResourceUtil.getStreamSafe("logback-base.xml")){
                    configurator.doConfigure(logbackBaseXmlStream);
                }
            }
        } catch (Exception exception) {
            JOptionPane.showMessageDialog(null, CharSequenceUtil.isNotEmpty(exception.getMessage()) ? exception.getMessage() : exception.toString(), "Error", JOptionPane.ERROR_MESSAGE);
        }

        Thread.setDefaultUncaughtExceptionHandler((thread, throwable) -> {
            log.error("Thread {} ", thread.getName(), throwable);
            if (throwable instanceof QSBasedException) {
                Notifications.getInstance().show(Notifications.Type.ERROR, throwable.getMessage());
            }
        });

        if (SystemInfo.isMacOS) {
            System.setProperty("apple.laf.useScreenMenuBar", "true");
            System.setProperty("apple.awt.application.name", appName);
            System.setProperty("apple.awt.application.appearance", "system");
        }
        if (SystemInfo.isLinux) {
            JFrame.setDefaultLookAndFeelDecorated(true);
            JDialog.setDefaultLookAndFeelDecorated(true);
        }
        if (!SystemInfo.isJava_9_orLater && System.getProperty("flatlaf.uiScale") == null) {
            System.setProperty("flatlaf.uiScale", "2x");
        }

        SwingUtilities.invokeLater(afterHandler);
    }

    public static void initialize(String[] args, String appName, Runnable afterHandler) {
        initialize(args, appName, appName, afterHandler);
    }

}
